package com.agilya.modele;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

import com.agilya.enumere.TypeAcces;
import com.agilya.utilitaires.Util;

public class QCM {

	private int id;
	private String libelle;
	private Date dateCreation;
	private int dureeValiditeJour;
	private int dureeFaisabiliteMinute;
	private boolean retourArriere;
	private boolean correctionDisponible;
	private String theme;
	private TypeAcces typeAcces;
	private double pointParBonneProposition;
	private double pointParMauvaiseProposition;
	private double plafondErreur;
	private String pageAccueil;
	private String header;
	private String pageFin;
	private int nbQuestion;
	private List<Question> listeQuestions;

	/**
	 * @param libelle
	 * @param dateCreation
	 * @param dureeValiditeJour
	 * @param dureeFaisabiliteMinute
	 * @param retourArriere
	 * @param correctionDisponible
	 * @param theme
	 * @param typeAcces
	 * @param pointParBonneProposition
	 * @param pointParMauvaiseProposition
	 * @param plafondErreur
	 * @param pageAccueil
	 * @param header
	 * @param pageFin
	 */
	public QCM(String libelle, Date dateCreation, int dureeValiditeJour, int dureeFaisabiliteMinute, boolean retourArriere, boolean correctionDisponible, String theme, TypeAcces typeAcces, double pointParBonneProposition, double pointParMauvaiseProposition, double plafondErreur, String pageAccueil,
			String header, String pageFin) {
		this.libelle = libelle;
		this.dateCreation = dateCreation;
		this.dureeValiditeJour = dureeValiditeJour;
		this.dureeFaisabiliteMinute = dureeFaisabiliteMinute;
		this.retourArriere = retourArriere;
		this.correctionDisponible = correctionDisponible;
		this.theme = theme;
		this.typeAcces = typeAcces;
		this.pointParBonneProposition = pointParBonneProposition;
		this.pointParMauvaiseProposition = pointParMauvaiseProposition;
		this.plafondErreur = plafondErreur;
		this.pageAccueil = pageAccueil;
		this.header = header;
		this.pageFin = pageFin;
	}

	/**
	 * @param id
	 * @param libelle
	 * @param dateCreation
	 * @param dureeValiditeJour
	 * @param dureeFaisabiliteMinute
	 * @param retourArriere
	 * @param correctionDisponible
	 * @param theme
	 * @param typeAcces
	 * @param pointParBonneProposition
	 * @param pointParMauvaiseProposition
	 * @param plafondErreur
	 * @param pageAccueil
	 * @param header
	 * @param pageFin
	 */
	public QCM(int id, String libelle, Date dateCreation, int dureeValiditeJour, int dureeFaisabiliteMinute, boolean retourArriere, boolean correctionDisponible, String theme, TypeAcces typeAcces, double pointParBonneProposition, double pointParMauvaiseProposition, double plafondErreur,
			String pageAccueil, String header, String pageFin, int nbQuestion) {
		this(libelle, dateCreation, dureeValiditeJour, dureeFaisabiliteMinute, retourArriere, correctionDisponible, theme, typeAcces, pointParBonneProposition, pointParMauvaiseProposition, plafondErreur, pageAccueil, header, pageFin);
		this.id = id;
		this.nbQuestion = nbQuestion;

	}

	/**
	 * 
	 * @param libelle
	 * @param dureeValiditeJour
	 * @param dureeFaisabiliteMinute
	 * @param retourArriere
	 * @param correctionDisponible
	 * @param pointParBonneProposition
	 * @param pointParMauvaiseProposition
	 * @param plafondErreur
	 */
	public QCM(String libelle, int dureeValiditeJour, int dureeFaisabiliteMinute, boolean retourArriere, boolean correctionDisponible, double pointParBonneProposition, double pointParMauvaiseProposition, double plafondErreur) {
		this(libelle, new Date(), dureeValiditeJour, dureeFaisabiliteMinute, retourArriere, correctionDisponible, null, TypeAcces.LIBRE, pointParBonneProposition, pointParMauvaiseProposition, plafondErreur, null, null, null);
	}

	/**
	 * @return the libelle
	 */
	public String getLibelle() {
		return libelle;
	}

	/**
	 * @param libelle
	 *            the libelle to set
	 */
	public void setLibelle(String libelle) {
		this.libelle = libelle;
	}

	/**
	 * @return the dateCreation
	 */
	public Date getDateCreation() {
		return dateCreation;
	}

	/**
	 * @param dateCreation
	 *            the dateCreation to set
	 */
	public void setDateCreation(Date dateCreation) {
		this.dateCreation = dateCreation;
	}

	/**
	 * @return the dureeValiditeJour
	 */
	public int getDureeValiditeJour() {
		return dureeValiditeJour;
	}

	/**
	 * @param dureeValiditeJour
	 *            the dureeValidite to set
	 */
	public void setDureeValiditeJour(int dureeValiditeJour) {
		this.dureeValiditeJour = dureeValiditeJour;
	}

	/**
	 * @return the dureeFaisabiliteMinure
	 */
	public int getDureeFaisabiliteMinute() {
		return dureeFaisabiliteMinute;
	}

	/**
	 * @param dureeFaisabiliteMinute
	 *            the dureeFaisabilite to set
	 */
	public void setDureeFaisabiliteMinute(int dureeFaisabiliteMinute) {
		this.dureeFaisabiliteMinute = dureeFaisabiliteMinute;
	}

	/**
	 * @return the retourArriere
	 */
	public boolean isRetourArriere() {
		return retourArriere;
	}

	/**
	 * @param retourArriere
	 *            the retourArriere to set
	 */
	public void setRetourArriere(boolean retourArriere) {
		this.retourArriere = retourArriere;
	}

	/**
	 * @return the correctionDisponible
	 */
	public boolean isCorrectionDisponible() {
		return correctionDisponible;
	}

	/**
	 * @param correctionDisponible
	 *            the correctionDisponible to set
	 */
	public void setCorrectionDisponible(boolean correctionDisponible) {
		this.correctionDisponible = correctionDisponible;
	}

	/**
	 * @return the theme
	 */
	public String getTheme() {
		return theme;
	}

	/**
	 * @param theme
	 *            the theme to set
	 */
	public void setTheme(String theme) {
		this.theme = theme;
	}

	/**
	 * @return the typeAcces
	 */
	public TypeAcces getTypeAcces() {
		return typeAcces;
	}

	/**
	 * @param typeAcces
	 *            the typeAcces to set
	 */
	public void setTypeAcces(TypeAcces typeAcces) {
		this.typeAcces = typeAcces;
	}

	/**
	 * @return the pointParBonneProposition
	 */
	public double getPointParBonneProposition() {
		return pointParBonneProposition;
	}

	/**
	 * @param pointParBonneProposition
	 *            the pointParBonneProposition to set
	 */
	public void setPointParBonneProposition(double pointParBonneProposition) {
		this.pointParBonneProposition = pointParBonneProposition;
	}

	/**
	 * @return the pointParMauvaiseProposition
	 */
	public double getPointParMauvaiseProposition() {
		return pointParMauvaiseProposition;
	}

	/**
	 * @param pointParMauvaiseProposition
	 *            the pointParMauvaiseProposition to set
	 */
	public void setPointParMauvaiseProposition(double pointParMauvaiseProposition) {
		this.pointParMauvaiseProposition = pointParMauvaiseProposition;
	}

	/**
	 * @return the plafondErreur
	 */
	public double getPlafondErreur() {
		return plafondErreur;
	}

	/**
	 * @param plafondErreur
	 *            the plafondErreur to set
	 */
	public void setPlafondErreur(double plafondErreur) {
		this.plafondErreur = plafondErreur;
	}

	/**
	 * @return the pageAccueil
	 */
	public String getPageAccueil() {
		return pageAccueil;
	}

	/**
	 * @param pageAccueil
	 *            the pageAccueil to set
	 */
	public void setPageAccueil(String pageAccueil) {
		this.pageAccueil = pageAccueil;
	}

	/**
	 * @return the header
	 */
	public String getHeader() {
		return header;
	}

	/**
	 * @param header
	 *            the header to set
	 */
	public void setHeader(String header) {
		this.header = header;
	}

	/**
	 * @return the pageFin
	 */
	public String getPageFin() {
		return pageFin;
	}

	/**
	 * @param pageFin
	 *            the pageFin to set
	 */
	public void setPageFin(String pageFin) {
		this.pageFin = pageFin;
	}

	/**
	 * @return the nbQuestion
	 */
	public int getNbQuestion() {
		return nbQuestion;
	}

	/**
	 * @param nbQuestion
	 *            the nbQuestion to set
	 */
	public void setNbQuestion(int nbQuestion) {
		this.nbQuestion = nbQuestion;
	}

	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}

	public List<Question> getListeQuestions() {
		return listeQuestions;
	}

	public void setListeQuestions(List<Question> listeQuestions) {
		this.listeQuestions = listeQuestions;
	}

	/**
	 * Calcule la note maximale du QCM
	 * 
	 * @return la note maximale
	 */
	private double calculerNoteMax() {

		double noteMax = 0;

		for (Question question : listeQuestions) {
			noteMax += pointParBonneProposition * question.calculerNoteMax();
		}
		return noteMax;
	}

	/**
	 * Calcule la note de l'apprenant selon ses réponses
	 * 
	 * @param reponsesQCM
	 *            HashMap de questions et de réponses aux propositions
	 * @return note de l'apprenant en pourcentage; ex = 50
	 */
	public double calculerNoteApprenant(HashMap<Question, List<Proposition>> reponsesQCM) {

		// Cas ou l'utilisateur n'a répondu a aucune question
		if (reponsesQCM == null) {
			return 0;
		}

		double noteApprenant = 0;

		for (Question question : listeQuestions) {
			noteApprenant += calculerNoteQuestion(question, reponsesQCM.get(question));
		}

		if (noteApprenant < 0) {
			return 0;
		}
		System.out.println("note max " + calculerNoteMax());
		double noteApprenantFinale = (noteApprenant / calculerNoteMax()) * 100;

		return Util.getArrondi(noteApprenantFinale);
	}

	/**
	 * Calcule la note pour une question
	 * 
	 * @param question
	 * @param listePropositionsRepondues
	 * @return la note pour la question
	 */
	public double calculerNoteQuestion(Question question, List<Proposition> listePropositionsRepondues) {

		double pointsQuestion;
		double noteQuestion = 0;

		List<Proposition> listePropositions = question.getListePropositions();
		// pour chaque proposition de la liste de proposition :
		for (Proposition proposition : listePropositions) {

			if (listePropositionsRepondues != null) {
				// RAZ à chaque propo
				pointsQuestion = 0;
				// On regarde pour toutes les propositions de la question si
				// l'apprenant y a répondu
				for (Proposition propositionRepondues : listePropositionsRepondues) {
					// on regarde si ses réponses sont correctes
					if (proposition.equals(propositionRepondues)) {
						if (proposition.estCorrecte()) {
							pointsQuestion += pointParBonneProposition * proposition.getCoefficient();
						}
						// Selon le coefficient, on retire des points par
						// mauvaise réponse.
						// les questions éliminatoires ne sont pas gérées.
						else {
							pointsQuestion -= pointParMauvaiseProposition * proposition.getCoefficient();

							if (proposition.estEliminatoire()) {
								pointsQuestion = 0;
								for (Proposition propositionAReetudier : listePropositions) {
									// on ne compte plus que les mauvaise réponses
									for (Proposition propositionMalRepondues : listePropositionsRepondues) {
										// Seulement si il a mal répondue
										if (propositionAReetudier.equals(propositionMalRepondues) && !proposition.estCorrecte()) {
											pointsQuestion -= pointParMauvaiseProposition * proposition.getCoefficient();
											System.out.println("proposition incorrecte" + pointsQuestion);
										}
									}
								}
								break;
							}
						}
					}
				}
				noteQuestion += question.getCoefficient() * pointsQuestion;

				// On gère le plafond d'erreur
				if (plafondErreur != 0 && -noteQuestion > plafondErreur) {
					noteQuestion = -plafondErreur;
					// System.out.println("plafond erreur " + plafondErreur + "notQuestion");
					break;
				}
			}
		}
		return Util.getArrondi(noteQuestion);
	}
}
